module BatchedSqlFu
  class BatchSqlCollection
    INSERT_RE = /INSERT INTO (.?[a-zA-Z0-9\_]*.?)\s+(\([^\)]*\))\s+VALUES\s*/i
  
    attr_reader :statements
    
    delegate :size, :join, :to => :statements
  
    def initialize(flush_batch_limit, connection)
      @flush_batch_limit = flush_batch_limit
      @connection        = connection
      @statements        = []
    end
  
    def <<( sql )
      @insert_into = extract_insert_statement_from sql if size == 0
      @statements << strip_insert_statement_from( sql )
      flush_now! if size >= @flush_batch_limit
    end
  
    def flush_now!
      @connection.execute( construct_mass_insert_sql )
      @statements = []
    end
  
    protected 
      def construct_mass_insert_sql
        "#{@insert_into} VALUES #{join(', ')}"
      end
  
      def extract_insert_statement_from( sql )
        if matches = sql.match(INSERT_RE)
          "INSERT INTO #{matches[1]} #{matches[2]}"
        else
          raise BatchedSqlFu::Error, "Can't exctract insert statment from #{sql}"
        end
      end
    
      def strip_insert_statement_from( sql )
        sql.gsub INSERT_RE, ''
      end
  end
end